package pers.guesswho;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;

import pers.guesswho.Guess.GuessType;

/**
 * Random guessing player. This player is for task B.
 *
 * You may implement/extend other interfaces or classes, but ensure ultimately
 * that this class implements the Player interface (directly or indirectly).
 */
public class RandomGuessPlayer implements Player {
	// 候选人组
	protected List<Person> persons = new ArrayList<>();
	// 候选属性集
	protected List<Attribute> attributes = new ArrayList<>();
	// 选择人
	protected Person chosenPerson;
	// 选择人名称
	protected String chosenName;

	/**
	 * Loads the game configuration from gameFilename, and also store the chosen
	 * person.
	 *
	 * @param gameFilename
	 *            Filename of game configuration.
	 * @param chosenName
	 *            Name of the chosen person for this player.
	 * @throws IOException
	 *             If there are IO issues with loading of gameFilename. Note you
	 *             can handle IOException within the constructor and remove the
	 *             "throws IOException" method specification, but make sure your
	 *             implementation exits gracefully if an IOException is thrown.
	 */
	public RandomGuessPlayer(String gameFilename, String chosenName) throws IOException {
		// 构造方法初始化数据
		this.chosenName = chosenName;
		BufferedReader gameReader = new BufferedReader(new FileReader(gameFilename));
		String line;
		Person person = new Person();
		int attrLength = 0;// 标记特征个数
		int attrFlag = 0;// 标记当前用户拥有的特征个数
		while ((line = gameReader.readLine()) != null) {

			if (line.length() == 0) {
				// 读到回车说明下一行是候选人名
				// 下一个候选人后将前一个候选人的信息保存进players
				line = gameReader.readLine();
				person = new Person();
				person.setName(line);
			} else if (line.length() != 0 && person.getName() != null) {
				// 将候选人的特性信息保存在实体类Person的Attributes中
				String[] fields = line.split(" ");
				HashMap<String, String> attr = new HashMap<>();
				person.getAttributes().put(fields[0], fields[1]);
				attrFlag++;
			} else {
				// 存储特征值
				String[] fields = line.split(" ");
				Attribute attribute = new Attribute();
				attribute.setAttrName(fields[0]);
				for (int i = 1; i < fields.length; i++) {
					attribute.getAttrVal().add(fields[i]);
				}
				attributes.add(attribute);
				attrLength++;
			}
			// 判断所有属性是否存储结束,若保存当前person对象
			if (attrFlag == attrLength) {
				if (chosenName.equals(person.getName())) {
					chosenPerson = person;
				}
				
				persons.add(person);
				attrFlag = 0;
			}

		}
		
		if (chosenPerson==null) {
			System.err.println("Uknown chosenName: " + chosenName);
		}

	} // end of RandomGuessPlayer()

	/**
	 * 通过随机函数,每次从候选的属性集中随机选取一个属性及属性值
	 */
	public Guess guess() {
		// 判断当前候选人组人数,若为1则直接返回唯一候选人名称
		if (persons.size() == 1) {
			return new Guess(GuessType.Person, "", persons.get(0).getName());
		}
		// 通过随机函数猜测一个特征属性及特征值
		else {
			Random random = new Random();
			// 随机选取一个特征属性
			Attribute attribute = attributes.get(random.nextInt(attributes.size()));
			// 随机选取一个特征属性中的特征值
			// 根据题目要求,未特殊处理只有一个特征值的属性,如facialHair white
			String attrVal = attribute.getAttrVal().get(random.nextInt(attribute.getAttrVal().size()));
			return new Guess(GuessType.Attribute, attribute.getAttrName(), attrVal);
		}
	} // end of guess()

	
	public boolean answer(Guess currGuess) {
		boolean result = false;
		// 若类型为person,则匹配人名
		if (currGuess.getType().equals(GuessType.Person) && chosenName.equals(currGuess.getValue())) {
			result = true;
		} // 若类型为attribute,则匹配属性名及特征值
		else if (currGuess.getType().equals(GuessType.Attribute)) {
			String chosenVal = chosenPerson.getAttributes().get(currGuess.getAttribute());
			if (chosenVal.equals(currGuess.getValue())) {
				result = true;
			}
		}
		return result;
	} // end of answer()

	
	/**
	 * 对猜测结果做处理,从特征属性集中删除已经猜测过的特征属性值
	 * 从候选人组中根据answer,删除不符合的候选人
	 * 只有当猜测类型为person,且answer为TRUE时receiveAnswer才为TRUE
	 */
	public boolean receiveAnswer(Guess currGuess, boolean answer) {
		boolean result = false;
		if (currGuess.getType().equals(GuessType.Person) && answer) {
			result = true;
		} else {
			// 从属性集中删除已经猜测过的属性
			for (int i = 0; i < attributes.size(); i++) {
				Attribute attribute = attributes.get(i);
				if (attribute.getAttrName().equals(currGuess.getAttribute())) {
					int j = attribute.getAttrVal().indexOf(currGuess.getValue());
					if (j!=-1) {
						attribute.getAttrVal().remove(j);
					}
					if (attribute.getAttrVal().size() == 0) {
						attributes.remove(i);
					}
					break;
				}
			}
			// 若answer为true则保留所有满足条件的候选人
			if (answer) {
				for (int i = 0; i < persons.size(); i++) {
					if (!persons.get(i).getAttributes().get(currGuess.getAttribute()).equals(currGuess.getValue())) {
						persons.remove(i);
					}
				}
			}else{// 若answer为false则去掉所有不满足条件的候选人
				for (int i = 0; i < persons.size(); i++) {
					if (persons.get(i).getAttributes().get(currGuess.getAttribute()).equals(currGuess.getValue())) {
						persons.remove(i);
					}
				}
			}
		}
		// placeholder, replace
		return result;
	} // end of receiveAnswer()
	
	//数据结构
	class Person {
		//候选人名
		private String name;
		//候选人特性
		private HashMap<String, String> Attributes = new HashMap<>();
		
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public HashMap<String, String> getAttributes() {
			return Attributes;
		}
		public void setAttributes(HashMap<String, String> attributes) {
			Attributes = attributes;
		}
		

	}

	class Attribute{
		private String attrName;
		private List<String> attrVal = new ArrayList<>();
		public String getAttrName() {
			return attrName;
		}
		public void setAttrName(String attrName) {
			this.attrName = attrName;
		}
		public List<String> getAttrVal() {
			return attrVal;
		}
		public void setAttrVal(List<String> attrVal) {
			this.attrVal = attrVal;
		}
		
	}

} // end of class RandomGuessPlayer


